package main

import (
	"fmt"
	"reflect"
)

/*
请编写一个案例，演示对(基本数据类型、interface{}、reflect.Value)
进行反射的基本操作 代码演示，见下面的表格：
*/

func reflectTest01(b interface{}){
	// 通过反射获取的传入的变量的 type(数据的类型) kind 值
	// 1. 先获取 reflect.Type（反射的类型）

	rType := reflect.TypeOf(b)
	fmt.Println("rType=",rType) // rType = int

	rVal := reflect.ValueOf(b)  // rVal = 100
	
	n2 := 2 + rVal.Int()
	// n2 := 2+ rVal //invalid operation: 2 + rVal (mismatched types int and reflect.Value
	fmt.Println("n2=",n2)
	fmt.Printf("rVal=%v rVal type=%T\n",rVal,rVal) // rVal=100 rVal type=reflect.Value

	// 下面将 rVal 转成 interface {}
	iV := rVal.Interface()
	// 将interface{} 通过断言转成需要的类型
	num2 := iV.(int)
	fmt.Printf("num2 = %v, type=%T",num2,num2) //num2 = 100, type=int



}

// 专门演示反射[对结构体的反射]
func reflectTest02(b interface{}){
	// 通过 反射获取的传入
	// 通过反射获取的传入的变量的 type(数据的类型) kind 值
	// 1. 先获取 reflect.Type（反射的类型）

	rType := reflect.TypeOf(b)
	fmt.Println("rType=",rType) // rType = int
	// 2.获取reflcet.Value
	rVal := reflect.ValueOf(b)  // rVal = 100

	// 3. 获取 变量对应的Kind
	// 1)rVal.Kind()
	kind1 := rVal.Kind()
	// 2)rType.Kind()
	kind2 := rType.Kind()

	fmt.Printf("kind=%v kind=%v\n",kind1,kind2)


	// 下面将 rVal 转成 interface {}
	iV := rVal.Interface()
	// 将interface{} 通过断言转成需要的类型
	// fmt.Printf("iv=%v,type=%T name=%v",iV,iV,iV.Name) // 编译时 iV.Name 不识别
	fmt.Printf("iv=%v,type=%T\n",iV,iV)
	// 简单使用了一个带检测的类型断言
	stu,ok := iV.(Student) // 能转成student 才转
	// 或者用switch 
	if ok{
		fmt.Printf("stu.Name=%v\n", stu.Name)
	}
}

type Student struct {
	Name string 
	Age int
}
type Monster struct {
	Name string 
	Age int
}

func main() {
	// 1. 先定义一个int
	// var num int = 100
	// reflectTest01(num)

	stu :=Student{
		Name:"tom",
		Age:12,
	}

	reflectTest02(stu) //iv={tom 12},type=main.Student

}